﻿/*************************************************************************************
 * 文 件 名:   HK_CreateGoByPath
 * 
 * 描    述:   根据LineRenderer路径生成模型，可用于数字城市项目中如生成沿路路灯、公共座椅等模型。
 * 
 *             TODO： 目前只支持两个点
 *                    目前只支持直线
 * 
 * 版    本：  V1.0
 * 创 建 者：  京产肠饭
 * 创建时间：  2023/4/5
 * 链   接：  https://gitee.com/JingChanChangFan/hk_-unity-tools
*************************************************************************************/

using UnityEngine;
using UnityEditor;
using System.Collections.Generic;

namespace HKTools
{
    [InitializeOnLoad]
    public class HK_CreateGoByPath : EditorWindow
    {
        const int CreateGoByPathPriority = 23;

        public GameObject target;

        int prefabCount;
        float offsetHeight;
        float offsetYEuler;

        [MenuItem("HKTools/CreateGoByPath(基于路径创建工具)", priority = CreateGoByPathPriority)]
        static void OpenWindow()
        {
            HK_CreateGoByPath createGoByPath = GetWindow<HK_CreateGoByPath>("CreateGoByPath");

            createGoByPath.Show();
        }

        void OnGUI()
        {
            EditorGUILayout.Space();

            GUILayout.BeginHorizontal();

            if (GUILayout.Button("生成LinePath", GUILayout.Width(100)))
            {
                CreateLinePath();
            }

            EditorGUILayout.Space();

            if (GUILayout.Button("重置LinePath坐标轴", GUILayout.Width(120)))
            {
                ResetLinePathAxis();
            }

            GUILayout.EndHorizontal();

            EditorGUILayout.Space();

            target = EditorGUILayout.ObjectField("需生成的物体", target, typeof(GameObject), true) as GameObject;

            EditorGUILayout.Space();

            prefabCount = EditorGUILayout.IntField("生成数量", prefabCount);

            EditorGUILayout.Space();

            offsetHeight = EditorGUILayout.FloatField("偏移高度", offsetHeight);

            EditorGUILayout.Space();

            offsetYEuler = EditorGUILayout.FloatField("Y轴偏移", offsetYEuler);

            EditorGUILayout.Space();

            if (GUILayout.Button("生成预设体", GUILayout.Width(100)))
            {
                CreateGoList();
            }

            EditorGUILayout.Space();

            if (GUILayout.Button("删除所有预设体", GUILayout.Width(100)))
            {
                DelectAllGos();
            }
        }

        void CreateLinePath()
        {
            EditorApplication.ExecuteMenuItem("GameObject/Create Empty");

            Selection.activeGameObject.name = "LinePath";

            LineRenderer lineRenderer = Undo.AddComponent<LineRenderer>(Selection.activeGameObject);
            lineRenderer.widthMultiplier = 0.1f;
            lineRenderer.useWorldSpace = false;

#if UNITY_2022_1_OR_NEWER
            lineRenderer.maskInteraction = SpriteMaskInteraction.VisibleInsideMask;
#endif

            lineRenderer.SetPosition(1, new Vector3(0, 0, 3));
            lineRenderer.shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.Off;
            lineRenderer.receiveShadows = false;
        }

        void ResetLinePathAxis()
        {
            if (Selection.count > 1)
            {
                Debug.LogWarning("选中物体多于一个");
                return;
            }

            if (Selection.count == 0)
            {
                Debug.LogWarning("没有选中物体");
                return;
            }

            if (Selection.activeGameObject.GetComponent<LineRenderer>() == null)
            {
                Debug.LogWarning("选中物体没有LineRender");
                return;
            }

            LineRenderer lineRenderer = Selection.activeGameObject.GetComponent<LineRenderer>();

            List<Transform> childList = new List<Transform>();

            // 将生成的子物体先移出来
            for (int i = 0; i < lineRenderer.transform.childCount; i++)
            {
                childList.Add(lineRenderer.transform.GetChild(i));
            }

            for (int i = 0; i < childList.Count; i++)
            {
                childList[i].SetParent(lineRenderer.transform.parent);
            }

            int posCount = lineRenderer.positionCount;

            Vector3 centerPos = Vector3.zero;

            for (int i = 0; i < posCount; i++)
            {
                centerPos += lineRenderer.GetPosition(i);
            }

            centerPos = centerPos / posCount;

            centerPos = lineRenderer.transform.TransformPoint(centerPos);

            Vector3 offset = centerPos - lineRenderer.transform.position;

            lineRenderer.transform.position = centerPos;

            for (int i = 0; i < posCount; i++)
            {
                Vector3 pos = lineRenderer.transform.TransformPoint(lineRenderer.GetPosition(i)) - offset;

                pos = lineRenderer.transform.InverseTransformPoint(pos);

                lineRenderer.SetPosition(i, pos);
            }

            // 将生成的子物体放回LineRenderer父物体下
            for (int i = 0; i < childList.Count; i++)
            {
                childList[i].SetParent(lineRenderer.transform);
            }
        }

        void CreateGoList()
        {
            if (Selection.count > 1)
            {
                Debug.LogWarning("选中物体多于一个");
                return;
            }

            if (Selection.count == 0)
            {
                Debug.LogWarning("没有选中物体");
                return;
            }

            if (Selection.activeGameObject.GetComponent<LineRenderer>() == null)
            {
                Debug.LogWarning("选中物体没有LineRender");
                return;
            }

            if (target == null)
            {
                Debug.LogWarning("没有选择预设体");
                return;
            }

            LineRenderer lineRenderer = Selection.activeGameObject.GetComponent<LineRenderer>();

            Vector3 startPos = lineRenderer.transform.TransformPoint(lineRenderer.GetPosition(0)) + Vector3.up * offsetHeight;
            Vector3 endPos = lineRenderer.transform.TransformPoint(lineRenderer.GetPosition(1)) + Vector3.up * offsetHeight;

            Vector3 dir = endPos - startPos;

            Quaternion qua = Quaternion.LookRotation(endPos - startPos, Vector3.up);

            Selection.activeGameObject = target;

            EditorApplication.ExecuteMenuItem("Window/General/Hierarchy");

            EditorApplication.ExecuteMenuItem("Edit/Duplicate");

            GameObject startGo = Selection.activeGameObject;

            startGo.transform.position = startPos;
            startGo.transform.rotation = qua;
            startGo.transform.SetParent(lineRenderer.transform);
            startGo.transform.Rotate(new Vector3(0, offsetYEuler, 0));

            EditorApplication.ExecuteMenuItem("Edit/Duplicate");

            GameObject endGo = Selection.activeGameObject;

            endGo.transform.position = endPos;
            endGo.transform.rotation = qua;
            endGo.transform.SetParent(lineRenderer.transform);
            endGo.transform.Rotate(new Vector3(0, offsetYEuler, 0));

            if (prefabCount <= 2)
            {
                Selection.activeGameObject = lineRenderer.gameObject;
                return;
            }

            int reaminCount = prefabCount - 2;
            int subCount = prefabCount - 1;

            for (int i = 0; i < reaminCount; i++)
            {
                Vector3 targetPos = startPos + dir / subCount * (i + 1);

                EditorApplication.ExecuteMenuItem("Edit/Duplicate");

                GameObject Go = Selection.activeGameObject;

                Go.transform.position = targetPos;
                Go.transform.rotation = qua;
                Go.transform.SetParent(lineRenderer.transform);
                Go.transform.Rotate(new Vector3(0, offsetYEuler, 0));
            }

            Selection.activeGameObject = lineRenderer.gameObject;
        }

        void DelectAllGos()
        {
            if (Selection.count > 1)
            {
                Debug.LogWarning("选中物体多于一个");
                return;
            }

            if (Selection.count == 0)
            {
                Debug.LogWarning("没有选中物体");
                return;
            }

            if (Selection.activeGameObject.GetComponent<LineRenderer>() == null)
            {
                Debug.LogWarning("选中物体没有LineRender");
                return;
            }

            if (target == null)
            {
                Debug.LogWarning("没有选择预设体");
                return;
            }

            if (Selection.activeGameObject.transform.childCount <= 0)
            {
                Debug.LogWarning("该物体下没有生成模型！");
                return;
            }

            List<GameObject> goList = new List<GameObject>();

            for (int i = 0; i < Selection.activeGameObject.transform.childCount; i++)
            {
                goList.Add(Selection.activeGameObject.transform.GetChild(i).gameObject);
            }

            for (int i = 0; i < goList.Count; i++)
            {
                Undo.DestroyObjectImmediate(goList[i]);
            }
        }
    }
}